import os

from sc_engine.apps import messages as msgs

from sc_engine.repositories import Repository, use
from sc_engine.repositories.stores import PickleFileStore

def make_app(app_name, root_config, config):
    data_dir = root_config['data_directory']

    store_filename = os.path.join(data_dir, app_name)
    store = PickleFileStore(store_filename)
    repo = Repository(store)

    app = ForcedDataApp(repo)

    return {
        msgs.PlayerAliasForced: app.player_alias_forced,
        msgs.PlayerNameForced: app.player_name_forced,
        msgs.MapNameForced: app.map_name_forced,

        msgs.PlayerDataAnnouncement: app.player_data_announcement,
        msgs.MapDataAnnouncement: app.map_data_announcement,
    }

class ForcedDataApp(object):
    """Assure that manually verified data is used.

    Sometimes information on players or maps on the kespa web site isn't the
    best source, either because non-korean viewers have their own community and
    names for players, or because the site was just plain wrong. This app will
    collect the data manually specified and make sure that when data
    announcements occur, that the correct data is included.
    """

    def __init__(self, repo):
        self.repo = repo

    @use('repo', 'players')
    def player_alias_forced(self, msg, players):
        data = players.setdefault(msg.player_id, {})

        aliases = data.get('aliases', [])
        aliases.append(msg.forced_alias)

        data['aliases'] = aliases

    @use('repo', 'players')
    def player_name_forced(self, msg, players):
        data = players.setdefault(msg.player_id, {})
        data['name'] = msg.forced_name

    @use('repo', 'maps')
    def map_name_forced(self, msg, maps):
        data = maps.setdefault(msg.map_id, {})
        data['name'] = msg.forced_name

    @use('repo', 'players')
    def player_data_announcement(self, msg, players):
        if msg.player_id not in players:
            return

        results = []
        known_data = players[msg.player_id]

        forced_name = known_data.get('name', None)
        if forced_name and msg.name.lower() != forced_name.lower():
            new_msg = msgs.PlayerNameDetermination(msg.player_id, forced_name)
            results.append(new_msg)

        aliases = [x.lower() for x in msg.aliases]
        forced_aliases = known_data.get('aliases', [])
        for forced_alias in forced_aliases:
            if forced_alias.lower() not in aliases:
                new_msg = msgs.PlayerAliasAddition(msg.player_id, forced_alias)
                results.append(new_msg)


        return results

    @use('repo', 'maps')
    def map_data_announcement(self, msg, maps):
        if msg.map_id not in maps:
            return

        forced_name = maps[msg.map_id]['name']
        if msg.name.lower() != forced_name.lower():
            return msgs.MapNameDetermination(msg.map_id, forced_name)

